package com.youtui.common.util;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;

import net.sf.ezmorph.object.DateMorpher;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.JSONUtils;

/**
 * @description. JSON工具包 @modificationHistory.
 * 
 * @author Lee 2013年8月7日下午5:43:04
 */
public class JsonUtil {

	public static final String DF_LONG_STR = "yyyy-MM-dd HH:mm:ss";
	public static final String DF_SHORT_STR = "yyyy-MM-dd";

	public static String getJsonValue(JSONObject obj, String key) {
		if (obj.containsKey(key)) {
			return obj.getString(key);
		}
		return key;

	}

	/**
	 * 从一个JSON 对象字符格式中得到一个java对象，形如： {"id" : idValue, "name" : nameValue,
	 * "aBean" : {"aBeanId" : aBeanIdValue, ...}}
	 * 
	 * @param object
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static Object getDTO(String jsonString, Class clazz) {
		JSONObject jsonObject = null;
		try {
			setDataFormat2JAVA();
			jsonObject = JSONObject.fromObject(jsonString);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return JSONObject.toBean(jsonObject, clazz);
	}

	/**
	 * 从一个JSON 对象字符格式中得到一个java对象，其中beansList是一类的集合，形如： {"id" : idValue, "name" :
	 * nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}, beansList:[{}, {},
	 * ...]}
	 * 
	 * @param jsonString
	 * @param clazz
	 * @param map
	 *            集合属性的类型 (key : 集合属性名, value : 集合属性类型class) eg: ("beansList" :
	 *            Bean.class)
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static Object getDTO(String jsonString, Class clazz, Map map) {
		JSONObject jsonObject = null;
		try {
			setDataFormat2JAVA();
			jsonObject = JSONObject.fromObject(jsonString);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return JSONObject.toBean(jsonObject, clazz, map);
	}

	/**
	 * 从一个JSON数组得到一个java对象数组，形如： [{"id" : idValue, "name" : nameValue}, {"id" :
	 * idValue, "name" : nameValue}, ...]
	 * 
	 * @param object
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static Object[] getDTOArray(String jsonString, Class clazz) {
		setDataFormat2JAVA();
		JSONArray array = JSONArray.fromObject(jsonString);
		Object[] obj = new Object[array.size()];
		for (int i = 0; i < array.size(); i++) {
			JSONObject jsonObject = array.getJSONObject(i);
			obj[i] = JSONObject.toBean(jsonObject, clazz);
		}
		return obj;
	}

	/**
	 * 从一个JSON数组得到一个java对象数组，形如： [{"id" : idValue, "name" : nameValue}, {"id" :
	 * idValue, "name" : nameValue}, ...]
	 * 
	 * @param object
	 * @param clazz
	 * @param map
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static Object[] getDTOArray(String jsonString, Class clazz, Map map) {
		setDataFormat2JAVA();
		JSONArray array = JSONArray.fromObject(jsonString);
		Object[] obj = new Object[array.size()];
		for (int i = 0; i < array.size(); i++) {
			JSONObject jsonObject = array.getJSONObject(i);
			obj[i] = JSONObject.toBean(jsonObject, clazz, map);
		}
		return obj;
	}

	/**
	 * 从一个JSON数组得到一个java对象集合
	 * 
	 * @param object
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List getDTOList(String jsonString, Class clazz) {
		setDataFormat2JAVA();
		JSONArray array = JSONArray.fromObject(jsonString);
		List list = new ArrayList();
		for (Iterator iter = array.iterator(); iter.hasNext();) {
			JSONObject jsonObject = (JSONObject) iter.next();
			list.add(JSONObject.toBean(jsonObject, clazz));
		}
		return list;
	}

	/**
	 * 从一个JSON数组得到一个java对象集合，其中对象中包含有集合属性
	 * 
	 * @param object
	 * @param clazz
	 * @param map
	 *            集合属性的类型
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List getDTOList(String jsonString, Class clazz, Map map) {
		setDataFormat2JAVA();
		JSONArray array = JSONArray.fromObject(jsonString);
		List list = new ArrayList();
		for (Iterator iter = array.iterator(); iter.hasNext();) {
			JSONObject jsonObject = (JSONObject) iter.next();
			list.add(JSONObject.toBean(jsonObject, clazz, map));
		}
		return list;
	}

	/**
	 * 从json HASH表达式中获取一个map，该map支持嵌套功能 形如：{"id" : "johncon", "name" : "小强"}
	 * 注意commons-collections版本，必须包含org.apache.commons.collections.map.
	 * MultiKeyMap
	 * 
	 * @param object
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Map getMapFromJson(String jsonString) {
		setDataFormat2JAVA();
		JSONObject jsonObject = JSONObject.fromObject(jsonString);
		Map map = new HashMap();
		for (Iterator iter = jsonObject.keys(); iter.hasNext();) {
			String key = (String) iter.next();
			map.put(key, jsonObject.get(key));
		}
		return map;
	}

	/**
	 * 从json数组中得到相应java数组 json形如：["123", "456"]
	 * 
	 * @param jsonString
	 * @return
	 */
	public static Object[] getObjectArrayFromJson(String jsonString) {
		JSONArray jsonArray = JSONArray.fromObject(jsonString);
		return jsonArray.toArray();
	}

	/**
	 * 把数据对象转换成json字符串 DTO对象形如：{"id" : idValue, "name" : nameValue, ...}
	 * 数组对象形如：[{}, {}, {}, ...] map对象形如：{key1 : {"id" : idValue, "name" :
	 * nameValue, ...}, key2 : {}, ...}
	 * 
	 * @param object
	 * @return
	 */
	public static String getJSONString(Object object) {
		String jsonString = null;

		if (object != null) {
			if (object instanceof Collection || object instanceof Object[]) {
				jsonString = JSONArray.fromObject(object, jsonConfig).toString();
			} else {
				jsonString = JSONObject.fromObject(object, jsonConfig).toString();
			}
		}
		return jsonString == null ? "{}" : jsonString;
	}

	/**
	 * 把数据对象转换成json字符串 DTO对象形如：{"id" : idValue, "name" : nameValue, ...}
	 * 
	 * @param object
	 * @return
	 */
	public static JSONObject getJSONObject(Object object) {
		JSONObject jsonObject = null;

		if (object != null) {
			if (object instanceof Collection || object instanceof Object[]) {
				jsonObject = new JSONObject();
			} else {
				jsonObject = JSONObject.fromObject(object, jsonConfig);
			}
		}
		return jsonObject;
	}

	/**
	 * 把数据对象转换成json字符串 数组对象形如：[{}, {}, {}, ...] map对象形如：{key1 : {"id" : idValue,
	 * "name" : nameValue, ...}, key2 : {}, ...}
	 * 
	 * @param object
	 * @return
	 */
	public static JSONArray getJSONArray(Object object) {
		JSONArray jsonArray = null;

		if (object != null) {
			if (object instanceof Collection || object instanceof Object[]) {
				jsonArray = JSONArray.fromObject(object, jsonConfig);
			} else {
				jsonArray = new JSONArray();
			}
		}
		return jsonArray;
	}

	private static void setDataFormat2JAVA() {
		// 设定日期转换格式
		JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[] { DF_SHORT_STR, DF_LONG_STR }));
	}

	public static class JsonDateValueProcessor implements JsonValueProcessor {

		private String format = DF_LONG_STR;

		public JsonDateValueProcessor() {

		}

		public JsonDateValueProcessor(String format) {
			this.format = format;
		}

		public Object processArrayValue(Object value, JsonConfig jsonConfig) {
			return process(value, jsonConfig);
		}

		public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
			return process(value, jsonConfig);
		}

		private Object process(Object value, JsonConfig jsonConfig) {
			if (value instanceof Date) {
				String str = new SimpleDateFormat(format).format((Date) value);
				return str;
			}
			return value == null ? null : value.toString();
		}

		public String getFormat() {
			return format;
		}

		public void setFormat(String format) {
			this.format = format;
		}

	}

	static JsonConfig jsonConfig = new JsonConfig();
	static {
		jsonConfig.registerJsonValueProcessor(Double.class, new JsonValueProcessor() {

			@Override
			/**
			 * 处理单个BigDecimal对象
			 */
			public Object processObjectValue(String propertyName, Object data, JsonConfig config) {
				Double d = (Double) data;
				return d + "";
			}

			@Override
			/**
			 * 处理数组中的BigDecimal对象
			 */
			public Object processArrayValue(Object data, JsonConfig config) {
				Double d = (Double) data;
				return d;
			}
		});
		jsonConfig.registerJsonValueProcessor(java.lang.Long.class, new JsonValueProcessor() {

			@Override
			public Object processObjectValue(String propertyName, Object data, JsonConfig config) {
				if (data != null) {
					return data.toString();
				}
				return "";
			}

			@Override
			public Object processArrayValue(Object data, JsonConfig jsonConfig) {
				return JSONArray.fromObject(data, jsonConfig).toString();
			}
		});
		jsonConfig.registerJsonValueProcessor(java.lang.Integer.class, new JsonValueProcessor() {

			@Override
			public Object processObjectValue(String propertyName, Object data, JsonConfig config) {
				if (data != null) {
					return data.toString();
				}
				return "";
			}

			@Override
			public Object processArrayValue(Object data, JsonConfig jsonConfig) {
				return JSONArray.fromObject(data, jsonConfig).toString();
			}
		});
		jsonConfig.registerJsonValueProcessor(java.util.Date.class, new JsonDateValueProcessor());
		jsonConfig.registerJsonValueProcessor(java.sql.Date.class, new JsonDateValueProcessor());
		jsonConfig.registerJsonValueProcessor(java.sql.Timestamp.class, new JsonDateValueProcessor());
	}

	/** 去掉的属性方法 */
	public static String fromObjectExcludes(Object object, String... excludes) {
		// 将PageBean对象转为json返回

		if (excludes != null && excludes.length > 0) {
			jsonConfig.setExcludes(excludes);
		}
		JSONObject jsonObject = JSONObject.fromObject(object, jsonConfig);
		String json = jsonObject.toString();
		return json;
	}

	/** 只取包含的属性方法 */
	public static String fromObjectIncludes(Object object, String... includes) {
		if (object == null) {
			return null;
		}
		Field[] fields0 = object.getClass().getDeclaredFields(); // 获取实体类的所有属性，返回Field数组
		Field[] fields1 = object.getClass().getSuperclass().getDeclaredFields();// 获取父类的所有属性，返回Field数组
		Field[] fields = ArrayUtils.addAll(fields0, fields1);
		if (fields.length == 0 || fields == null) {
			return null;
		}
		String[] properties = new String[fields.length];
		int index = 0;
		for (Field field : fields) {
			properties[index] = field.getName();
			index++;
		}
		if (includes == null || includes.length == 0) {
			return null;
		}
		String[] minus = minus(properties, includes);
		if (minus != null && minus.length > 0) {
			jsonConfig.setExcludes(minus);
		}
		JSONObject jsonObject = JSONObject.fromObject(object, jsonConfig);
		String json = jsonObject.toString();
		return json;
	}

	// 求两个数组的差集
	public static String[] minus(String[] arr1, String[] arr2) {
		LinkedList<String> list = new LinkedList<String>();
		LinkedList<String> history = new LinkedList<String>();
		String[] longerArr = arr1;
		String[] shorterArr = arr2;
		// 找出较长的数组来减较短的数组
		if (arr1.length > arr2.length) {
			longerArr = arr2;
			shorterArr = arr1;
		}
		for (String str : longerArr) {
			if (!list.contains(str)) {
				list.add(str);
			}
		}
		for (String str : shorterArr) {
			if (list.contains(str)) {
				history.add(str);
				list.remove(str);
			} else {
				if (!history.contains(str)) {
					list.add(str);
				}
			}
		}

		String[] result = {};
		return list.toArray(result);
	}

}
